﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Slqj.Common
{
    /// <summary>
    /// 字节串二进制序列化填充类
    /// </summary>
    public class ArcByteSet
    {
        /// <summary>
        /// 字节缓冲区
        /// </summary>
        List<byte> m_buf = new List<byte>();

        #region 填充
        public void Set(byte val)
        {
            m_buf.Add(val);
        }

        public void Set(sbyte val)
        {
            m_buf.Add((byte)val);
        }

        public void Set(decimal val)
        {
            Set(Convert.ToDouble(val));
        }

        public void Set(bool val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(char val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(double val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(float val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(int val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(long val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(short val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(uint val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(ulong val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(ushort val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val));
        }

        public void Set(string val)
        {
            if (null == val)
                val = string.Empty;
            m_buf.AddRange(Encoding.UTF8.GetBytes(val));
            m_buf.Add((byte)0);
        }

        public void Set(DateTime val)
        {
            m_buf.AddRange(BitConverter.GetBytes(val.ToBinary()));
        }
        #endregion

        /// <summary>
        /// 转出为字节数组
        /// </summary>
        /// <returns></returns>
        public byte[] ToBytes()
        {
            return m_buf.ToArray();
        }

        /// <summary>
        /// 转出为Base64串
        /// </summary>
        /// <returns></returns>
        public string ToBase64()
        {
            try
            {
                return Convert.ToBase64String(m_buf.ToArray(), 0, m_buf.Count);
            }
            catch (System.Exception)
            {
                return string.Empty;
            }
        }
    }

    /// <summary>
    /// 字节串二进制序列化获取类
    /// </summary>
    public class ArcByteGet
    {
        byte[] m_buf;

        int m_curPos = 0;

        public ArcByteGet(byte[] bytes)
        {
            m_buf = bytes;
        }

        public ArcByteGet(string base64Str)
        {
            if (string.IsNullOrEmpty(base64Str))
                m_buf = new byte[0];
            else
            {
                try
                {
                    m_buf = Convert.FromBase64String(base64Str);
                }
                catch (System.Exception)
                {
                    m_buf = new byte[0];
                }

            }
        }

        bool IsNextValid(int len)
        {
            return m_curPos + len <= m_buf.Length;
        }

        void Reset()
        {
            m_curPos = 0;
        }

        #region 获取
        public bool GetBool(bool defaultVal)
        {
            if (!IsNextValid(sizeof(bool)))
                return defaultVal;
            bool res = BitConverter.ToBoolean(m_buf, m_curPos);
            m_curPos += sizeof(bool);
            return res;
        }

        public bool GetBool()
        {
            return GetBool(false);
        }

        public byte GetByte(byte defaultVal)
        {
            if (!IsNextValid(sizeof(byte)))
                return defaultVal;
            return m_buf[m_curPos++];
        }

        public byte GetByte()
        {
            return GetByte(0);
        }

        public sbyte GetSByte(sbyte defaultVal)
        {
            if (!IsNextValid(sizeof(sbyte)))
                return defaultVal;
            return (sbyte)m_buf[m_curPos++];
        }

        public sbyte GetSByte()
        {
            return GetSByte(0);
        }

        public char GetChar(char defaultVal)
        {
            if (!IsNextValid(sizeof(char)))
                return defaultVal;
            char res = BitConverter.ToChar(m_buf, m_curPos);
            m_curPos += sizeof(char);
            return res;
        }

        public char GetChar()
        {
            return GetChar('\0');
        }

        public DateTime GetDateTime(DateTime defaultVal)
        {
            if (!IsNextValid(sizeof(long)))
                return defaultVal;
            long res = BitConverter.ToInt64(m_buf, m_curPos);
            m_curPos += sizeof(long);
            return DateTime.FromBinary(res);
        }

        public DateTime GetDateTime()
        {
            return GetDateTime(DateTime.MinValue);
        }

        public decimal GetDecimal(decimal defaultVal)
        {
            if (!IsNextValid(sizeof(double)))
                return defaultVal;
            double res = BitConverter.ToDouble(m_buf, m_curPos);
            m_curPos += sizeof(double);
            return Convert.ToDecimal(res);
        }

        public decimal GetDecimal()
        {
            return GetDecimal(0);
        }

        public double GetDouble(double defaultVal)
        {
            if (!IsNextValid(sizeof(double)))
                return defaultVal;
            double res = BitConverter.ToDouble(m_buf, m_curPos);
            m_curPos += sizeof(double);
            return res;
        }

        public double GetDouble()
        {
            return GetDouble(0);
        }

        public short GetShort(short defaultVal)
        {
            if (!IsNextValid(sizeof(short)))
                return defaultVal;
            short res = BitConverter.ToInt16(m_buf, m_curPos);
            m_curPos += sizeof(short);
            return res;
        }

        public short GetShort()
        {
            return GetShort(0);
        }

        public int GetInt(int defaultVal)
        {
            if (!IsNextValid(sizeof(int)))
                return defaultVal;
            int res = BitConverter.ToInt32(m_buf, m_curPos);
            m_curPos += sizeof(int);
            return res;
        }

        public int GetInt()
        {
            return GetInt(0);
        }

        public long GetLong(long defaultVal)
        {
            if (!IsNextValid(sizeof(long)))
                return defaultVal;
            long res = BitConverter.ToInt64(m_buf, m_curPos);
            m_curPos += sizeof(long);
            return res;
        }

        public long GetLong()
        {
            return GetLong(0);
        }

        public float GetFloat(float defaultVal)
        {
            if (!IsNextValid(sizeof(float)))
                return defaultVal;
            float res = BitConverter.ToSingle(m_buf, m_curPos);
            m_curPos += sizeof(float);
            return res;
        }

        public float GetFloat()
        {
            return GetFloat(0);
        }

        public string GetString(string defaultVal)
        {
            int end = 0;
            for (end = m_curPos; end < m_buf.Length && m_buf[end] != 0; end++) ;
            int len = end - m_curPos;
            if (!IsNextValid(len))
                return defaultVal;
            string res = Encoding.UTF8.GetString(m_buf, m_curPos, len);
            m_curPos = end + 1;
            return res;
        }

        public string GetString()
        {
            return GetString(string.Empty);
        }

        public ushort GetUShort(ushort defaultVal)
        {
            if (!IsNextValid(sizeof(ushort)))
                return defaultVal;
            ushort res = BitConverter.ToUInt16(m_buf, m_curPos);
            m_curPos += sizeof(ushort);
            return res;
        }

        public ushort GetUShort()
        {
            return GetUShort(0);
        }

        public uint GetUInt(uint defaultVal)
        {
            if (!IsNextValid(sizeof(uint)))
                return defaultVal;
            uint res = BitConverter.ToUInt32(m_buf, m_curPos);
            m_curPos += sizeof(uint);
            return res;
        }

        public uint GetUInt()
        {
            return GetUInt(0);
        }

        public ulong GetULong(ulong defaultVal)
        {
            if (!IsNextValid(sizeof(ulong)))
                return defaultVal;
            ulong res = BitConverter.ToUInt64(m_buf, m_curPos);
            m_curPos += sizeof(ulong);
            return res;
        }

        public ulong GetULong()
        {
            return GetULong(0);
        }
        #endregion
    }
}
